﻿using System;
using System.Collections.Generic;
using System.Web.Mvc;
using NLog;

namespace IceDog.DNF.Program.Mvc5.Filters
{
    /// <summary>
    /// 时间过滤器
    /// </summary>
    public class TimingActionFilterAttribute : ActionFilterAttribute
    {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger(typeof(TimingActionFilterAttribute));
        //创建字典来记录开始时间，key是访问的线程Id.
        private readonly Dictionary<int, DateTime> _start = new Dictionary<int, DateTime>();
        //创建字典来记录当前访问的页面Url.
        private readonly Dictionary<int, string> _url = new Dictionary<int, string>();

        /// <summary>在执行操作方法之前由 ASP.NET MVC 框架调用。</summary>
        /// <param name="filterContext">筛选器上下文。</param>
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
            //过滤掉ChildAction, 因为ChildAction实际上不是一个单独的页面
            if (filterContext.IsChildAction) return;
            var currentThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
            try
            {
                _start.Add(currentThreadId, DateTime.Now);
                _url.Add(currentThreadId, filterContext.HttpContext.Request.Url == null
                    ? string.Empty
                    : filterContext.HttpContext.Request.Url.AbsoluteUri);
            }
            catch (Exception ex)
            {
                Logger.Error(ex.ToString());
            }
        }

        /// <summary>在执行操作结果后由 ASP.NET MVC 框架调用。</summary>
        /// <param name="filterContext">筛选器上下文。</param>
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            base.OnResultExecuted(filterContext);
            var currentThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
            if (!_start.ContainsKey(currentThreadId)) return;
            try
            {
                //计算出当前页面访问耗时
                var timeSpan = (DateTime.Now - _start[currentThreadId]).TotalMilliseconds;
                if (timeSpan > 500)//如果耗时超过500毫秒，就是用log4net打印出，具体是哪个页面访问超过了500豪秒，具体使用了多长时间。
                {
                    var msg = $"运行时间超过500毫秒，共花费{timeSpan}毫秒.  URL: {_url[currentThreadId]}";
                    filterContext.HttpContext.Response.Write(msg);
                    Logger.Info(msg);
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex.ToString());
            }
            finally
            {
                _start.Remove(currentThreadId);
                _url.Remove(currentThreadId);
            }
        }
    }
}